<?php

namespace app\common\service;

use app\common\service\traits\InstanceTrait;
use app\model\sys\Area;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\facade\Cache;
use think\facade\Db;

class CommonAreaService
{

    use InstanceTrait;

    protected string $cacheTag = 'area';

    /** 根据上级ID查询所有子孙级
     * @param int $pid
     * @return Query
     */
    public function childrenQuery(int $pid): Query
    {

        return Db::table(" (
	SELECT
		@ids AS _ids,
		@l:=@l+1 AS level,
		(SELECT @ids := GROUP_CONCAT( id ) FROM `area` WHERE FIND_IN_SET( pid, @ids )) cids 
	FROM
		`area`,
		( SELECT @ids:=$pid , @l:=0) pid 
	) AS scope,
	`area`  ")
            ->whereRaw(" scope._ids IS NOT NULL AND FIND_IN_SET( area.id, scope._ids ) AND area.id<>$pid ");
    }

    /**
     * 根据上级ID查询出所有子孙
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function getChildren(int $pid): array|\think\Collection
    {
        return $this->childrenQuery($pid)->select();
    }

    /**
     * 根据上级ID，查询出所有子孙分ID集合
     * @param int $pid
     * @return array
     */
    public function getChildrenIds(int $pid): array
    {
        return $this->childrenQuery($pid)->column("id");
    }

    /** 根据分类id获取下级分类
     * @param $arr
     * @param $pid
     * @param $lev
     * @return array 一维数组
     */
    public function tree($data,$pid=0,$lev=1): array
    {
        $subs = array();
        foreach($data as $v)
        {
            if($v['pid'] == $pid){
                $v['lev'] = $lev;
                $v['l_title'] = str_repeat("——", $lev-1).$v['title'];
                $subs[] = $v;
                $subs = array_merge($subs,$this->tree($data, $v['id'], $lev+1));
            }
        }
        return $subs;
    }

    /**
     * 二维数组
     * @param $data
     * @param $pid
     * @param $lev
     * @return array
     */
    public function childrenTree($data, $pid=0, $lev=1): array
    {

        $subs = array();
        foreach($data as $v)
        {
            if($v['pid'] == $pid){
                $v['lev'] = $lev;
                $v['children'] = $this->childrenTree($data, $v['id'], $lev+1);
                $subs[] = $v;
            }
        }
        return $subs;
    }

    /**
     * 获取所有地区组合成的树形数组
     * @return mixed
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getAllChildrenTree(): mixed
    {

        $tree = Cache::get("areaAllChildrenTree",'');
        if (!$tree){
            $list = Area::where('pid','<>',0)->field("id,title,pid,code,type")->select();
            $tree = $this->childrenTree($list, 1);
            Cache::tag($this->cacheTag)->set("areaAllChildrenTree", $tree);
        }
        return $tree;

    }

}
